package Client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.util.StringTokenizer;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import Client.JFrameCliente;
import Client.excepciones.IncorrectCodeException;
import Client.excepciones.NullPasswordException;
import Client.excepciones.NullUserException;
import Client.excepciones.UnableToConnectException;
import Client.excepciones.UnexpectedErrorException;
import Client.excepciones.UserNotInsertedException;

/**
 * Clase JDialog para introducir los datos de login de un usuario, y la IP del servidor al que desea conectarse.
 * @author inlacou
 *
 */
public class JDialogUsuario extends JDialog {

	private Dimension minSize;
	private JLabel jl;
	private JTextField jt;
	private JTextField jip;
	private JPasswordField jp;
	private JLabel jlMensaje;
	private JButton jbAceptar;
	private JButton jbCancelar;
	private JPanel jpU;
	private JPanel jpB;

	public String IPdir;

	public ClienteTCP cTCP;

	/**
	 * Constructor de la clase JDialogUsuario.
	 * @param jFP
	 * @param modality
	 */
	public JDialogUsuario(JFrame jFP, ModalityType modality) {
		super(jFP, "Usuario", modality);

		//Inicializacion de Variables.
		minSize = new Dimension(250, 130);
		jl = new JLabel();
		jt = new JTextField(10);
		resetTextField(jt);
		jip = new JTextField(10);
		resetTextField(jip);
		jp = new JPasswordField(10);
		jlMensaje = new JLabel();
		jlMensaje.setAlignmentX(CENTER_ALIGNMENT);
		jlMensaje.setForeground(Color.LIGHT_GRAY);
		jpU = new JPanel(new FlowLayout(FlowLayout.CENTER));
		jpB = new JPanel(new FlowLayout(FlowLayout.CENTER));
		jbAceptar = new JButton("Aceptar");
		jbAceptar.setEnabled(false);
		jbCancelar = new JButton("Cancelar");
		jpU.add(jl);
		jpU.add(jt);
		jpU.add(jip);
		jpU.add(jp);
		jp.setVisible(false);
		jpB.add(jbAceptar);
		jpB.add(jbCancelar);

		IP();

		//Listeners.
		//KeyListener que va a permitir que cualquier pulsacion de "enter" sobre los botones con este Listener tendran como resultado la seleccion de uno de los dos botones de la pantalla.
		KeyListener enter = new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == 10){
					if(jbCancelar.isFocusOwner()){
						jbCancelar.doClick();
					}else{
						jbAceptar.doClick();
					}
				}
			}
		};

		jbAceptar.addKeyListener(enter);
		jbAceptar.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				JButton b = (JButton) arg0.getSource();
				Component c = b.getParent();
				while( !(c instanceof JDialogUsuario) ){
					c = c.getParent();
				}

				if(jl.getText().equals("Contrasena: ")){
					try{
						cTCP.sendPassword(new String(jp.getPassword()));
						if(cTCP.waitPasswordAck()){
							((JDialogUsuario)c).dispose();
							c = c.getParent();
							((JFrameCliente)c).setCTCP(cTCP);
							((JFrameCliente)c).conectado();
						}else{
							jp.setText("");
							jp.setBorder(BorderFactory.createLineBorder(Color.RED));
							jlMensaje.setText("Contrasena incorrecta.");
						}
					} catch (IncorrectCodeException e) {
						jp.setText("");
						jp.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Respuesta incorrecta del servidor.");
					} catch (NullPasswordException e) {
						jp.setText("");
						jp.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Contrasena nula.");
					} catch (IOException e) {
						jp.setText("");
						jp.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Error en el envio de la Contrasena.");
					} catch (UserNotInsertedException e) {
						jp.setText("");
						jp.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Error en el envio de la Contrasena.");
					} catch (UnexpectedErrorException e) {
						//jt.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Error inesperado, pruebe de nuevo.");
					}	
				} else if(jl.getText().equals("Usuario: ")){
					try {
						cTCP.sendUserName(jt.getText());
						if(cTCP.waitUserNameAck()){
							jlMensaje.setText("");
							resetTextField(jt);
							contrasena();
							jp.grabFocus();
						}else{
							jt.setBorder(BorderFactory.createLineBorder(Color.RED));
							jlMensaje.setText("Usuario incorrecto.");
						}
					} catch (NullUserException e) {
						jt.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Error: Nombre de usuario nulo.");
					} catch (IOException e) {
						jt.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Error en el envio del nombre de Usuario.");
					} catch (IncorrectCodeException e) {
						jt.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Respuesta inesperada del servidor.");
					} catch (NullPointerException e){
						jt.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Imposible establecer la conexion.");
						IP();
					} catch (UnexpectedErrorException e) {
						jlMensaje.setText("Error inesperado, pruebe de nuevo.");
					}
				} else if(jl.getText().equals("Direccion IP: ")){
					if(IPformat(jip.getText())){
						try {
							cTCP = new ClienteTCP(jip.getText());
							cTCP.leerRespuestaConexion();
							jlMensaje.setText("");
							IPdir = jip.getText();
							resetTextField(jip);
							usuario();
							jt.grabFocus();
							IPdir = jip.getText();
							resetTextField(jip);
							usuario();
						} catch (IOException e) {
							jip.setBorder(BorderFactory.createLineBorder(Color.RED));
							jlMensaje.setText("Error de conexion. Pruebe de nuevo.");
						} catch (IncorrectCodeException e) {
							jip.setBorder(BorderFactory.createLineBorder(Color.RED));
							jlMensaje.setText("Respuesta inesperada. Pruebe de nuevo.");
						} catch (UnableToConnectException e) {
							jlMensaje.setText("Imposible establecer conexion.");
						}
						jt.grabFocus();
					}else{
						jip.setBorder(BorderFactory.createLineBorder(Color.RED));
						jlMensaje.setText("Formato de direccion IP incorrecto.");
					}
				}
			}

		});

		jbCancelar.addKeyListener(enter);
		jbCancelar.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				JButton b = (JButton) arg0.getSource();
				Component c = b.getParent();
				while( !(c instanceof JDialogUsuario) ){
					c = c.getParent();
				}

				((JDialogUsuario)c).dispose();
				try {
					cTCP.cerrar();
				} catch (IOException e) {
				} catch (IncorrectCodeException e) {
				} catch (UnexpectedErrorException e) {
				} catch (NullPointerException e){
				}
			}
		});

		jt.addKeyListener(enter);
		jt.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent arg0) {
			}

			@Override
			public void keyReleased(KeyEvent arg0) {
			}

			@Override
			public void keyPressed(KeyEvent arg0) {
				if(jt.getForeground().equals(Color.LIGHT_GRAY) && !(arg0.getKeyCode() == 10)){	
					if(arg0.getKeyCode() == KeyEvent.VK_ESCAPE){
						jbCancelar.doClick();
					}else{
						jt.setText("");
						jt.setForeground(Color.black);
						jbAceptar.setEnabled(true);
					}
				}
			}
		});

		jip.addKeyListener(enter);
		jip.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent arg0) {
			}

			@Override
			public void keyReleased(KeyEvent arg0) {
			}

			@Override
			public void keyPressed(KeyEvent arg0) {
				if(jip.getForeground().equals(Color.LIGHT_GRAY) && !(arg0.getKeyCode() == 10)){	
					if(arg0.getKeyCode() == KeyEvent.VK_ESCAPE){
						jbCancelar.doClick();
					}else{
						jip.setText("");
						jip.setForeground(Color.black);
						jbAceptar.setEnabled(true);
					}
				}
			}
		});

		this.addWindowListener(new WindowListener() {

			@Override
			public void windowOpened(WindowEvent arg0) {

			}

			@Override
			public void windowIconified(WindowEvent arg0) {

			}

			@Override
			public void windowDeiconified(WindowEvent arg0) {

			}

			@Override
			public void windowDeactivated(WindowEvent arg0) {

			}

			@Override
			public void windowClosing(WindowEvent arg0) {
				try {
					cTCP.cerrar();
				} catch (IOException e) {
				} catch (IncorrectCodeException e) {
				} catch (UnexpectedErrorException e) {
				} catch (NullPointerException e){
				}
			}

			@Override
			public void windowClosed(WindowEvent arg0) {

			}

			@Override
			public void windowActivated(WindowEvent arg0) {

			}
		});

		jp.addKeyListener(enter);

		//Propiedades.
		this.setLocation(	(int)jFP.getLocation().getX()+(int)jFP.getSize().getWidth()/3,
				(int)jFP.getLocation().getY()+(int)jFP.getSize().getHeight()/3
		); //Coloca esta ventana en una posicion relativa a su JFrame padre.
		this.setMinimumSize(minSize);
		this.setLayout(new BorderLayout());
		this.getContentPane().add(jpU, BorderLayout.NORTH);
		this.getContentPane().add(jlMensaje, BorderLayout.CENTER);
		this.getContentPane().add(jpB, BorderLayout.SOUTH);
		this.setTitle("Connect");
	}

	/**
	 * Cambia el JLabel y los JTextfield de modo que solo queden los referentes a la Contrasenya.
	 */
	private void contrasena(){
		jl.setText("Contrasena: ");
		jt.setVisible(false);
		jp.setVisible(true);
		jp.requestFocus();
		jip.setVisible(false);
	}

	/**
	 * Cambia el JLabel y los JTextfield de modo que solo queden los referentes al Usuario.
	 */
	private void usuario(){
		jl.setText("Usuario: ");
		jt.setVisible(true);
		jt.requestFocus();
		jp.setVisible(false);
		jip.setVisible(false);
	}

	/**
	 * Cambia el JLabel y los JTextfield de modo que solo queden los referentes a la IP.
	 */
	private void IP(){
		jl.setText("Direccion IP: ");
		jt.setVisible(false);
		jp.setVisible(false);
		jip.setVisible(true);
		jip.requestFocus();
	}

	/**
	 * Metodo que comprueba si el String introducido por parametro tiene formato de direccion IP.
	 * @param ip
	 * @return true si tiene formato de direccion IP.
	 */
	private boolean IPformat(String ip){
		try{
			StringTokenizer st = new StringTokenizer(ip, ".");
			for(int i = 0; i < 4; i++){
				int num = (Integer.parseInt(st.nextToken()));
				if(num<0 || num>255){
					return false;
				}
			}
			if(st.hasMoreTokens()){
				return false;
			}
		}catch(Exception e){
			return false;
		}
		return true;
	}

	/**
	 * Metodo que resetea el estado del JTextField introducido por parametro.
	 * @param jtf
	 */
	private void resetTextField(JTextField jtf){
		jtf.setForeground(Color.LIGHT_GRAY);
		jtf.setText("Escriba aqui");
	}



}
